package main

import (
	"fmt"
	"reflect"
)

/*
文档： https://studygolang.com/static/pkgdoc/pkg/reflect.htm
Type 提供了获得某个变量的类型的描述信息
Value 提供了对变量进行反射操作的方法
参考博客： https://studygolang.com/articles/12348?fr=sidebar
*/

func reflect_int() {
	num := 100
	numType := reflect.TypeOf(num)                 // 返回一个 Type 类型，该类型实际上是 interface 类型
	fmt.Printf("num type = %v \n", numType.Kind()) // num type = int

	numValue := reflect.ValueOf(num)                       // 返回一个保管了 num 值得接口
	fmt.Printf("num type = %v \n", numValue.Type().Kind()) // num type = int
	fmt.Printf("num kind = %v \n", numValue.Kind())        // num kind = int

	// 获得值
	fmt.Printf("num get with Value= %v \n", numValue.Int())

	// 修改值
	modifyNum := numValue.Int() * 10
	// panic: reflect: reflect.flag.mustBeAssignable using unaddressable value
	// numValue.SetInt(modifyNum)
	if numValue.CanAddr() {
		numValue.Addr().SetInt(modifyNum)
	} else {
		fmt.Println("无法寻址，不能改变值！")
	}
	if numValue.CanSet() {
		fmt.Println("可以被修改！")
	} else {
		fmt.Println("不可以被修改！")
	}

	// 修改为原类型
	// 本方法返回v当前持有的值（表示为/保管在interface{}类型）
	numValueInterface := numValue.Interface()
	fmt.Printf("num get with interface = %v \n", numValueInterface.(int))

}

// 总之修改值得话必须是指针类型的
func reflect_int_modify() {
	num := 100
	numValueWithAddr := reflect.ValueOf(&num)

	numType := reflect.TypeOf(num)                 // 返回一个 Type 类型，该类型实际上是 interface 类型
	fmt.Printf("num type = %v \n", numType.Kind()) // num type = int

	fmt.Printf("num type = %v \n", numValueWithAddr.Type().Kind()) // num type = ptr
	fmt.Printf("num kind = %v \n", numValueWithAddr.Kind())        // num kind = ptr

	// 获得值
	fmt.Printf("num get with Value= %v \n", numValueWithAddr.Int())

	if numValueWithAddr.Elem().CanAddr() {
		fmt.Println("可以寻址！")
	} else {
		fmt.Println("无法寻址！")
	}
	if numValueWithAddr.Elem().CanSet() {
		fmt.Println("可以被修改！")
	} else {
		fmt.Println("不可以被修改！")
	}

	// 要想修改必须在ValueOf的时候传递地址进去
	numValueWithAddr.Elem().SetInt(199)
	fmt.Println(num) // 1000
}

func main() {
	reflect_int()
	fmt.Println("***********************")
	reflect_int_modify()
}
